#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>

#include <netinet/in.h>
#include <sys/select.h>
#include <sys/time.h>
#include <unistd.h>
#include <sys/select.h>

#include "common.h"
#define IP "172.16.0.11"
#define Port 8889

Client clients[CLIENT_MAX];
int main()
{
    // socket
    int iServer = socket(AF_INET, SOCK_STREAM, 0);
    if (-1 == iServer)
    {
        printf("create socket error\r\n");
        return -1;
    }
    printf("create socket ok\r\n");
    // bind
    struct sockaddr_in stServer;
    memset(&stServer, 0, sizeof(struct sockaddr_in));
    stServer.sin_family = AF_INET;
    stServer.sin_port = htons(Port);
    stServer.sin_addr.s_addr = inet_addr(IP);
    int opt = 1;
    // 设置端口复用
    setsockopt(iServer, SOL_SOCKET, SO_REUSEADDR, (const void *)&opt, sizeof(opt));
    int iRet = bind(iServer, (struct sockaddr *)&stServer, sizeof(struct sockaddr_in));
    if (iRet != 0)
    {
        return -1;
    }
    printf("bind ok\r\n");
    // listen
    iRet = listen(iServer, 5);
    if (iRet != 0)
    {
        return -1;
    }
    printf("listen ok\r\n");

    // 读集合
    fd_set stReadSet; // 1024
    FD_ZERO(&stReadSet);

    // char buf[BUF_SIZE] = {0};
    FD_SET(iServer, &stReadSet);
    int iMax = iServer;

    struct timeval tv = {5, 0};

    // 创建Mysql指针
    MYSQL sql_ptr;
    /**
     * 初始化数据库
     */
    if (EXIT_FAILURE == myMysql_init(&sql_ptr, "175.178.28.47", "root", "123456", "ANIMAL_SYSTEM"))
        printf("初始化MYSQL成功失败\r\n");
    else
        printf("初始化MYSQL成功\r\n");
    while (1)
    {
        fd_set readtmp = stReadSet;
        printf("---- second %ld ----\r\n", tv.tv_sec);
        tv.tv_sec = 5;
        iRet = select(iMax + 1, &readtmp, NULL, NULL, &tv);
        printf("---- select %d %ld ----\r\n", iRet, tv.tv_sec);
        if (iRet < 0)
        {
            printf("出了点小问题...\r\n");
            continue;
        }
        if (0 == iRet)
        {
            // do some thing
            printf("等待新客户端链接...\r\n");
            continue;
        }
        int i = 0;
        for (i = 0; i < iMax + 1; i++)
        {
            if (!FD_ISSET(i, &readtmp))
            {
                continue;
            }
            if (i == iServer)
            {
                // accept client
                int iClient = accept(iServer, NULL, NULL);
                if (iClient < 0)
                {
                    continue;
                }
                FD_SET(iClient, &stReadSet);
                /**
                 * @brief 判断是stm32客户端还是qt客户端
                 *        并赋值给响应的客户端数组成员
                 */
                int tmpFd = isStm32OrQtClient(iClient);
                int i = 0;
                // 添加进客户端数组
                for (; i < CLIENT_MAX; i++)
                {
                    if (clients[i].clientType == 0)
                    {
                        clients[i].clientType = tmpFd;
                        clients[i].clientFd = iClient;
                        printf("isStm32OrQtClient 返回的数为: %d\n", tmpFd);
                        printf("iclient is %s , fd is %d\r\n",
                               (clients[i].clientType == QT) ? "QTclient" : (clients[i].clientType == STM32) ? "STM32client"
                                                                                                        : "未知客户端",
                               iClient);
                        break;
                    }
                }
                if (iClient > iMax)
                {
                    iMax = iClient;
                }
            }
            else
            {
                // recv and send
                // memset(buf, 0, BUF_SIZE);
                printf("---- recv sockid is %d ----\r\n", i);
                /**
                 * 处理接收的数据
                 * 参数是fd, 链接客户端的文件描述符
                 * */
                iRet = stm32_qt_recv(i, &sql_ptr);
                /**
                 * 返回值大于 0 操作成功
                 * */
                if (iRet > 0)
                { // todo 操作成功
                    printf("---- %s 执行成功 ----\r\n", __func__);
                }
                else
                {
                    printf("---- recv error id is %d ----\r\n", i);
                    FD_CLR(i, &stReadSet);
                    close(i);
                    if (i == iMax)
                    {
                        int j = i - 1;
                        while (j > 0)
                        {
                            if (FD_ISSET(j, &stReadSet))
                            {
                                iMax = j;
                                break;
                            }
                            j--;
                        }
                    }

                    // 将把客户端数组中对应的客户端清除
                    int k = 0;
                    for (; k < CLIENT_MAX; k++)
                    {
                        if (clients[k].clientFd == i)
                        {
                            clients[k].clientFd = 0;
                            clients[k].clientType = 0;
                            printf("---- 有客户端退出，清理了一次文件描述符: %d ----\n", i);
                        }
                    }
                }
            }
        }
        // do some thing
    }
}